﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;

namespace GameAndNode_updated
{

	class LogicNode
	{
		public GameFiled field;
		public Frame frame;
		public Drawer drw;
		List<GameNode> nodeList;
		GameNode targetNode;
		private ConsoleColor targetColor = ConsoleColor.Blue;
		public int CountOfNodes { get; private set; }
		ConsoleColor bodyColor = ConsoleColor.Red;
		ConsoleColor headColor = ConsoleColor.Green;
		Random nodeRnd;
		char bodySymbol = '$';
		char headSymbol = '@';
		char targetSymbol = '#';
		int totalCountAte;
		int speed = 350;
		int numberOfSpeed = 1;
		ConsoleKeyInfo key = default(ConsoleKeyInfo);
		ConsoleKeyInfo currentKey = default(ConsoleKeyInfo);
		private readonly Keyboard kb;
		bool isGameOver = false;
		bool isPaused = true;
		bool dotIsChoosed = false;
		bool isNewRound = false;


		public LogicNode(GameFiled field, Keyboard keyB)
		{
			this.field = field;
			frame = new Frame(this.field);
			drw = new Drawer();
			drw.FrameDrawing('#', this.field, frame);
			nodeRnd = new Random();

			kb = keyB;
			kb.KeyLeft += MoveNodeLeft;
			kb.KeyRigth += MoveNodeRight;
			kb.KeyDown += MoveNodeDown;
			kb.KeyUp += MoveNodeUp;
		}

		public CurrentDOT DirectionChecking(ConsoleKeyInfo cki)
		{
			if (cki.Key == ConsoleKey.LeftArrow)
			{
				return CurrentDOT.Left;
			}
			if (cki.Key == ConsoleKey.RightArrow)
			{
				return CurrentDOT.Right;
			}
			if (cki.Key == ConsoleKey.DownArrow)
			{
				return CurrentDOT.Down;
			}
			return CurrentDOT.Up;
		}

		private void MoveNodeUp(object sender, EventArgs e)
		{
			if (!ValidationChecks.IsOnTheField(nodeList[0].XNode, nodeList[0].YNode - 1, field) || ValidationChecks.IsDuplicateNodes(nodeList[0].XNode, nodeList[0].YNode - 1, nodeList))
			{
				isGameOver = true;
			}
			if (ValidationChecks.IsOnTheField(nodeList[0].XNode, nodeList[0].YNode - 1, field) && !ValidationChecks.IsDuplicateNodes(nodeList[0].XNode, nodeList[0].YNode - 1, nodeList))
			{
				if (DirectionChecking(currentKey) != CurrentDOT.Down)
				{
					nodeList[0].MoveUp();
				}
			}
		}

		private void MoveNodeDown(object sender, EventArgs e)
		{
			if (!ValidationChecks.IsOnTheField(nodeList[0].XNode, nodeList[0].YNode + 1, field) || ValidationChecks.IsDuplicateNodes(nodeList[0].XNode, nodeList[0].YNode + 1, nodeList))
			{
				isGameOver = true;
			}
			if (ValidationChecks.IsOnTheField(nodeList[0].XNode, nodeList[0].YNode + 1, field) && !ValidationChecks.IsDuplicateNodes(nodeList[0].XNode, nodeList[0].YNode + 1, nodeList))
			{
				if (DirectionChecking(currentKey) != CurrentDOT.Up)
				{
					nodeList[0].MoveDown();
				}
			}
		}

		private void MoveNodeRight(object sender, EventArgs e)
		{
			if (!ValidationChecks.IsOnTheField(nodeList[0].XNode + 1, nodeList[0].YNode, field) || ValidationChecks.IsDuplicateNodes(nodeList[0].XNode + 1, nodeList[0].YNode, nodeList))
			{
				isGameOver = true;
			}
			if (ValidationChecks.IsOnTheField(nodeList[0].XNode + 1, nodeList[0].YNode, field) && !ValidationChecks.IsDuplicateNodes(nodeList[0].XNode + 1, nodeList[0].YNode, nodeList))
			{
				if (DirectionChecking(currentKey) != CurrentDOT.Left)
				{
					nodeList[0].MoveRight();
				}
			}
		}

		private void MoveNodeLeft(object sender, EventArgs e)
		{
			if (!ValidationChecks.IsOnTheField(nodeList[0].XNode - 1, nodeList[0].YNode, field) || ValidationChecks.IsDuplicateNodes(nodeList[0].XNode - 1, nodeList[0].YNode, nodeList))
			{
				isGameOver = true;
			}
			if (ValidationChecks.IsOnTheField(nodeList[0].XNode - 1, nodeList[0].YNode, field) && !ValidationChecks.IsDuplicateNodes(nodeList[0].XNode - 1, nodeList[0].YNode, nodeList))
			{
				if (DirectionChecking(currentKey) != CurrentDOT.Right)
				{
					nodeList[0].MoveLeft();
				}
			}
		}

		public void StartGame()
		{
			string choice;
			do
			{
				NodeMoveLogic();
				choice = drw.GameOverInfo(field);
				drw.ClearGameInfo(field);
			} while (choice == "Y");

		}

		public void NextRoundSnakePosition()
		{
			GameNode head = new GameNode(nodeRnd.Next(field.StartX + 3, field.StartX + field.Width - 3), nodeRnd.Next(field.StartY, field.StartY + field.Height - 1), headSymbol, headColor);
			nodeList = new List<GameNode>()
				{
					head,
					new GameNode(head.XNode+1, head.YNode, bodySymbol, bodyColor),
					new GameNode(head.XNode+2, head.YNode, bodySymbol, bodyColor)
				};
		}

		public void RandomPlacment(List<GameNode> listOfNodes)
		{
			int x;
			int y;
			foreach (var node in listOfNodes)
			{
				do
				{
					x = nodeRnd.Next(field.StartX, field.StartX + field.Width - 1);
					y = nodeRnd.Next(field.StartX, field.StartX + field.Width - 1);
				} while (ValidationChecks.IsDuplicateNodes(x, y, listOfNodes) || !ValidationChecks.IsOnTheField(x, y, field));
				node.XNode = x;
				node.YNode = y;
			}
		}

		public void NextTargetCreation()
		{
			do
			{
				targetNode = new GameNode(nodeRnd.Next(field.StartX, field.StartX + field.Width - 1), nodeRnd.Next(field.StartY, field.StartY + field.Height - 1), targetSymbol, ConsoleColor.Blue);
			} while (ValidationChecks.IsDuplicateNodes(targetNode.XNode, targetNode.YNode, nodeList));
		}

		public void SnakeBodyMoving(List<GameNode> list, ConsoleKeyInfo key)
		{

			if (DirectionChecking(key) == CurrentDOT.Down 
				&& ValidationChecks.IsOnTheField(nodeList[0].XNode, nodeList[0].YNode + 1, field) && !ValidationChecks.IsDuplicateNodes(nodeList[0].XNode, nodeList[0].YNode + 1, nodeList))
			{
				for (int i = list.Count - 1; i >= 1; i--)
				{
					list[i].XNode = list[i - 1].XNode;
					list[i].YNode = list[i - 1].YNode;
				}
			}

			if (DirectionChecking(key) == CurrentDOT.Up 
				&& ValidationChecks.IsOnTheField(nodeList[0].XNode, nodeList[0].YNode - 1, field) && !ValidationChecks.IsDuplicateNodes(nodeList[0].XNode, nodeList[0].YNode - 1, nodeList))
			{
				for (int i = list.Count - 1; i >= 1; i--)
				{
					list[i].XNode = list[i - 1].XNode;
					list[i].YNode = list[i - 1].YNode;
				}
			}

			if (DirectionChecking(key) == CurrentDOT.Left
				&& ValidationChecks.IsOnTheField(nodeList[0].XNode-1, nodeList[0].YNode, field) && !ValidationChecks.IsDuplicateNodes(nodeList[0].XNode - 1, nodeList[0].YNode, nodeList))
			{
				for (int i = list.Count - 1; i >= 1; i--)
				{
					list[i].XNode = list[i - 1].XNode;
					list[i].YNode = list[i - 1].YNode;
				}
			}

			if (DirectionChecking(key) == CurrentDOT.Right 
				&& ValidationChecks.IsOnTheField(nodeList[0].XNode + 1, nodeList[0].YNode, field) && !ValidationChecks.IsDuplicateNodes(nodeList[0].XNode + 1, nodeList[0].YNode, nodeList))
			{
				for (int i = list.Count - 1; i >= 1; i--)
				{
					list[i].XNode = list[i - 1].XNode;
					list[i].YNode = list[i - 1].YNode;
				}
			}
		}

		public void isDirectionIsCorrect(ConsoleKeyInfo newKey, ConsoleKeyInfo currKey)
		{
			if (DirectionChecking(newKey) == CurrentDOT.Down && DirectionChecking(currKey) == CurrentDOT.Up)
			{
				key = currentKey;
			}
			if (DirectionChecking(newKey) == CurrentDOT.Up && DirectionChecking(currKey) == CurrentDOT.Down)
			{
				key = currentKey;
			}
			if (DirectionChecking(newKey) == CurrentDOT.Left && DirectionChecking(currKey) == CurrentDOT.Right)
			{
				key = currentKey;
			}
			if (DirectionChecking(newKey) == CurrentDOT.Right && DirectionChecking(currKey) == CurrentDOT.Left)
			{
				key = currentKey;
			}
		}

		public void PressedButton(ConsoleKeyInfo pressedKey)
		{
			if (pressedKey.Key != ConsoleKey.UpArrow && pressedKey.Key != ConsoleKey.DownArrow && pressedKey.Key != ConsoleKey.LeftArrow
				&& pressedKey.Key != ConsoleKey.RightArrow && pressedKey.Key != ConsoleKey.P)
			{
				if (!isPaused)
				{
					key = currentKey;
				}
			}

			if (pressedKey.Key == ConsoleKey.P)
			{
				isPaused = true;
				//currentKey = pressedKey;
			}

			if (pressedKey.Key == ConsoleKey.UpArrow || pressedKey.Key == ConsoleKey.DownArrow || pressedKey.Key == ConsoleKey.LeftArrow || pressedKey.Key == ConsoleKey.RightArrow)
			{
				if (ValidationChecks.NextStepIsOnSecondNode(nodeList, pressedKey) && isPaused)
				{
					isPaused = true;
				}
				if (!ValidationChecks.NextStepIsOnSecondNode(nodeList, pressedKey) && isPaused)
				{
					isPaused = false;
				}
			}
		}

		public void NodeMoveLogic()
		{
			totalCountAte = 0;
			speed = 350;
			numberOfSpeed = 1;
			NextRoundSnakePosition();
			NextTargetCreation();
			isPaused = true;
			dotIsChoosed = false;
			key = default(ConsoleKeyInfo);
			currentKey = default(ConsoleKeyInfo);

			do
			{
				drw.ScoreInfo(field, totalCountAte, speed, numberOfSpeed);
				drw.DrawGameNode(targetNode, targetColor, targetSymbol);
				bool isTragetGet = false;
				isGameOver = false;

				do
				{
					if (Console.KeyAvailable)
					{
						key = Console.ReadKey(true);
						if (!dotIsChoosed)
						{
							dotIsChoosed = true;
							currentKey = key;
							if (key.Key != ConsoleKey.UpArrow && key.Key != ConsoleKey.DownArrow && key.Key != ConsoleKey.LeftArrow
								&& key.Key != ConsoleKey.RightArrow && key.Key != ConsoleKey.P)
							{
								dotIsChoosed = false;
								currentKey = default(ConsoleKeyInfo);
							}
						}
					}
					PressedButton(key);
					if (!isPaused && dotIsChoosed)
					{
						isDirectionIsCorrect(key, currentKey);
						SnakeBodyMoving(nodeList, key);
						kb.ControlKeyboard(key);
						isPaused = false;
						currentKey = key;
					}
					

					for (int n = 0; n < nodeList.Count; n++)
					{
						drw.DrawGameNode(nodeList[n], nodeList[n].NodeColor, nodeList[n].NodeSymbol);
					}
					if (ValidationChecks.IsOnTarget(nodeList[0].XNode, nodeList[0].YNode, targetNode))
					{
						totalCountAte++;
						speed -= 20;
						numberOfSpeed++;
						isTragetGet = true;
						nodeList.Add(new GameNode(nodeList[nodeList.Count - 1].XNode, nodeList[nodeList.Count - 1].YNode, bodySymbol, bodyColor));
						NextTargetCreation();
						if (nodeList.Count == 5)
						{
							isNewRound = true;
						}
					}
					System.Threading.Thread.Sleep(speed);
					foreach (var item in nodeList)
					{
						drw.ClearGameNode(item);
					}
					if (isGameOver)
					{
						nodeList.Clear();
						isTragetGet = true;
					}
				} while (isTragetGet == false);

				if (isTragetGet)
				{
					drw.ClearGameNode(targetNode);
				}
				if (isNewRound)
				{
					nodeList.Clear();
					NextRoundSnakePosition();
					key = default(ConsoleKeyInfo);
					currentKey = default(ConsoleKeyInfo);
					isPaused = true;
					dotIsChoosed = false;
					isNewRound = false;
				}

			} while (!isGameOver);
		}

		public NodePosition CheckNextPosition(int X, int Y)
		{
			if (ValidationChecks.IsDuplicateNodes(X, Y, nodeList))
			{
				return NodePosition.OnNode;
			}
			if (ValidationChecks.IsOnTheField(X, Y, field)==false)
			{
				return NodePosition.OnBorderAndOut;
			}
			return NodePosition.FreePosition;
		}
			
	}

	enum NodePosition
	{
		OnNode,
		OnBorderAndOut,
		FreePosition
	}

	enum CurrentDOT
	{
		Up,
		Down,
		Left,
		Right
	}
}
	 